<?php

class db
{
    protected $link = null;
    protected $res = null;
    protected $is_connected = false;

    private function __construct() {}

    protected static function &getInstance()
    {
        static $instance = null;
        if (is_null($instance)) {
            $instance = new self();
        }

        return $instance;
    }

    function __destruct()
    {
        $this->_close();
    }

    protected function _connect($host = null, $user = null, $pass = null, $db = null, $params = array())
    {
        if (is_resource($mixed)) {
            $this->link = $mixed;
        } elseif (
            !is_null($host)    &&
            !is_null($user)     &&
            !is_null($pass)     &&
            !is_null($db)
        ) {
            $this->_connect_to_db($mixed, $user, $pass, $db, $params);
        } else {
            self::log_it('Wrong parameters for DB');
        }
        $this->is_connected = true;
    }

    protected function _connect_to_db($host, $user, $pass, $db, $params = array())
    {
        $this->link = mysql_pconnect($host, $user, $pass);
        if (!is_resource($this->link)) {
            self::log_it('Can\'t connect: ' . mysql_error($this->link));
        }
    	if (!mysql_select_db($db, $this->link)) {
    	    self::log_it('Can\'t select DB');
    	}
    	$charset = null;
    	if (isset($params["charset"])) {
    	    $params["charset"] = strtoupper($params["charset"]);
    	    $charset = preg_replace("/[^A-Z0-9]/s", "", $params["charset"]);
    	}
    	if (isset($charset)) {
    	    if (is_string($this->_query("SET NAMES {$charset}"))) {
    	        self::log_it("Can’t set charset.");
    	    }
    	}
    }

    protected function _query($query)
    {
        $this->res = mysql_query($query, $this->link);
    	if ($this->res === false) {
		    return 'Error query: ' . mysql_error($this->link);
    	}
    	return true;
    }

    protected function _select($query)
    {
        $res = $this->_query($query);
        if (is_string($res)) {
            return $res;
        }
        $result = array();
        $row = array();
    	while ($row = $this->_getItem()) {
            $result[] = $row;
    	}
    	return $result;
    }

    protected function _selectRow($query)
    {
        $res = $this->_query($query);
        if (is_string($res)) {
            return $res;
        }
        $result = array();
    	if ($row = $this->_getItem()) {
            $result = $row;
    	}
    	return $result;
    }

    protected function _selectColumn($query)
    {
        $res = $this->_query($query);
        if (is_string($res)) {
            return $res;
        }
        $result = array();
    	while ($row = $this->_getItem()) {
            $result[] = reset($row);
    	}
    	return $result;
    }

    protected function _selectScalar($query)
    {
        $res = $this->_query($query);
        if (is_string($res)) {
            return null;
        }
        $result = null;
    	if ($row = $this->_getItem()) {
            $result = reset($row);
    	}
    	return $result;
    }

    protected function _getInsertId()
    {
        return mysql_insert_id($this->link);
    }

    protected function _getItem()
    {
        $item = null;
        if ($tmp = mysql_fetch_array($this->res, MYSQL_ASSOC)) {
            $item = $tmp;
        }
        return $item;
    }

    protected function _close()
    {
        if ($this->is_connected) {
            mysql_close($this->link);
        }
        $this->is_connected = false;
    }

    protected function log_it($msg, $exit=true)
    {
        if ($exit) {
            throw new Exception($msg);
        }
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Интерфейс ///////////////////////////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////////////////////////////

    public static function connect($host = null, $user = null, $pass = null, $db = null, $params = array())
    {
        if (self::getInstance()->is_connected) {
            self::log_it("Already connected.");
        }
        self::getInstance()->_connect($host, $user, $pass, $db, $params);
    }

    public static function query($query)
    {
        if (! self::getInstance()->is_connected) {
            self::log_it("Connected absent.");
        }
        return self::getInstance()->_query($query);
    }

    public static function select($query)
    {
        if (! self::getInstance()->is_connected) {
            self::log_it("Connected absent.");
        }
        return self::getInstance()->_select($query);
    }

    public static function selectRow($query)
    {
        if (! self::getInstance()->is_connected) {
            self::log_it("Connected absent.");
        }
        return self::getInstance()->_selectRow($query);
    }

    public static function selectColumn($query)
    {
        if (! self::getInstance()->is_connected) {
            self::log_it("Connected absent.");
        }
        return self::getInstance()->_selectColumn($query);
    }

    public static function selectScalar($query)
    {
        if (! self::getInstance()->is_connected) {
            self::log_it("Connected absent.");
        }
        return self::getInstance()->_selectScalar($query);
    }

    public static function getInsertId()
    {
        if (! self::getInstance()->is_connected) {
            self::log_it("Connected absent.");
        }
        return self::getInstance()->_getInsertId($query);
    }

    public static function close($query)
    {
        if (! self::getInstance()->is_connected) {
            self::log_it("Connected absent.");
        }
        return self::getInstance()->_close($query);
    }
}

?>